package common

import (
	"math/rand"
	"src/zeus/linmath"
	"sync"
	"time"
)

type SRand struct {
	Sr     *rand.Rand
	lk     sync.Mutex
	isLock bool
}

var GlobalRand *SRand

func GlobalRandInit() {
	GlobalRand = NewSRand(true)
}

func GetGlobalRand() *SRand {
	if GlobalRand == nil {
		GlobalRandInit()
	}
	return GlobalRand
}

func NewSRand(isLock bool) *SRand {
	srand := &SRand{
		Sr:     rand.New(rand.NewSource(time.Now().UnixNano())),
		isLock: isLock,
	}
	if srand.isLock {
		srand.lk = sync.Mutex{}
	}
	return srand
}

// Rand go的随机函数是半开区间，这里是全闭区间
func (sr *SRand) Rand(min, max int32) int32 {
	if min >= max {
		return min
	}
	var rd int32 = 0
	if sr.isLock {
		sr.lk.Lock()
		rd = sr.Sr.Int31n(max + 1 - min)
		sr.lk.Unlock()
	} else {
		rd = sr.Sr.Int31n(max + 1 - min)
	}
	return min + rd
}

// Rand go的随机函数 Int63n 是半开区间，这里是全闭区间
func (sr *SRand) RandI64(min, max int64) int64 {
	if min >= max {
		return min
	}
	var rd int64 = 0
	if sr.isLock {
		sr.lk.Lock()
		rd = sr.Sr.Int63n(max + 1 - min)
		sr.lk.Unlock()
	} else {
		rd = sr.Sr.Int63n(max + 1 - min)
	}
	return min + rd
}

// Rand2 半开区间
func (sr *SRand) Rand2(max int32) int32 {
	if max <= 0 {
		return max
	}
	if sr.isLock {
		sr.lk.Lock()
		defer sr.lk.Unlock()
	}
	return sr.Sr.Int31n(max)
}

// 得到随机概率下标-权重
func (sr *SRand) GetRandomIndex(rateNum int, data []int32) (int, bool) {
	//随机一个数
	randNum := sr.Rand2(int32(rateNum))
	var tempSum int32
	for index, value := range data {
		tempSum += value
		if tempSum >= randNum {
			return index, true
		}
	}
	return 0, false
}

// 得到随机下标
func (sr *SRand) GetRandomIndex2(len int) (int32, bool) {
	if len == 0 {
		return 0, false
	}
	return sr.Rand2(int32(len)), true
}

// 得到随机下标的值
func (sr *SRand) GetRandomValue(data []int32) (int32, bool) {
	//随机一个数
	if len(data) == 0 {
		return 0, false
	}
	return data[sr.Rand2(int32(len(data)))], true

}

// 得到随机下标的值
func (sr *SRand) GetRandomString(length int) (res string) {
	//随机一个数
	const simbols = "!@#$%^&*()-=_+[]{};':\",.<>/?\\|"
	const str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=_"
	var index int
	for i := 0; i < length; i++ {
		index = int(sr.Rand2(int32(len(str))))
		res += string(str[index])
	}
	return
}
func (sr *SRand) Happen(weight, max int) bool {
	return sr.Sr.Intn(max) <= weight
}

// 随机附近点
func RandomMove(rand *SRand, pos linmath.Vector3, rangeSize int32) linmath.Vector3 {
	randX := rand.Rand(-rangeSize, rangeSize)
	randZ := rand.Rand(-rangeSize, rangeSize)
	wanderPos := linmath.NewVector3(pos.X+float32(randX)/100.0, pos.Y, pos.Z+float32(randZ)/100.0)
	//logger.Info("fsm randpos is ", wanderPos)
	return wanderPos
}
